package main

import (
	"fmt"
	"math/rand"
	"time"
)

type worker struct {
	id   int
	done chan struct{}
}

func genWorker(id int) worker {
	return worker{id, make(chan struct{})}
}

func (w worker) work() chan string {
	c := make(chan string)
	go func() {
		i := 0
		for {
			select {
			case <-time.After(time.Duration(rand.Intn(2000)) * time.Millisecond):
				c <- fmt.Sprintf("no.%d mes %d", w.id, i)
			case <-w.done:
				fmt.Printf("genner %d is quitting\n", w.id)
				w.done <- struct{}{}
				return
			}
			i++
		}
	}()
	return c
}

func (w worker) quit() {
	w.done <- struct{}{}
	<-w.done
	fmt.Printf("genner %d is successfully quitted\n", w.id)
}

func fanIn(chs ...chan string) chan string {
	c := make(chan string)
	for _, ch := range chs {
		//chCopy属于括号内，而ch属于括号外
		go func(chCopy chan string) {
			for {
				c <- <-chCopy
			}
		}(ch)
	}
	return c
}

// 缺点：不能处理不确定个数的channel
func selctFanIn(c1, c2 chan string) chan string {
	c := make(chan string)
	go func() {
		var hasValue = false
		var m string
		for {
			var tc chan string
			if hasValue {
				tc = c
			}
			select {
			case m = <-c1:
				hasValue = true
			case m = <-c2:
				hasValue = true
			case tc <- m:
				hasValue = false
			}
		}
	}()
	return c
}

func nonBlockWait(c chan string) (string, bool) {
	select {
	case m := <-c:
		return m, true
	default:
		return "", false
	}
}

func timeoutWait(c chan string, timeout time.Duration) (string, bool) {
	select {
	case m := <-c:
		return m, true
	case <-time.After(timeout):
		return "", false
	}
}

func main() {

	m1, m2 := genWorker(1), genWorker(2)
	r := fanIn(m1.work(), m2.work())
	for i := 0; i < 100; i++ {
		fmt.Println(<-r)
	}
	m1.quit()
	m2.quit()
}
